<?php

namespace common\models;

use Yii;

/**
 * This is the model class for table "UserAccount".
 */
class UserAccount extends ActiveRecord {

    // only define rules for those attributes that
    // will receive user inputs.
    public function rules()
    {
        return [
            [['user_id', 'usable', 'frozen', 'recharge', 'withdraw', 'consume', 'earn'], 'required'],
            [['user_id', 'usable', 'frozen', 'recharge', 'withdraw', 'consume', 'earn'], 'integer'],
        ];
    }
    /**
     * @name 字段名称
     * @return array
     */
    public function attributeLabels()
    {
        return [
            'user_id' => '用户',
            'usable' => '可用余额',
            'frozen' => '冻结中',
            'recharge' => '充值总计',
            'withdraw' => '提现总计',
            'consume' => '消费总计',
            'earn' => '赚取总计',
        ];
    }

    /**
     * @name 获取user信息
     * @return \yii\db\ActiveQuery
     */
    public function getUser()
    {
        return $this->hasOne(User::className(), ['id' => 'user_id']);
    }

    /**
     * @name 初始化用户账户信息
     * @return \yii\db\ActiveQuery
     */
    public static function initAccount($userId)
    {
        $account = new UserAccount();
        $account->user_id = $userId;
        foreach(['usable', 'frozen', 'recharge', 'withdraw', 'consume', 'earn'] as $key) {
            $account->{$key} = 0;
        }
        return $account->save();
    }

    /**
     * @name 充值到账，修改用户余额
     * @param $amount int 充值金额
     * @return boolean
     */
    public function recharge($amount)
    {
        $amount = (int)$amount;
        if($amount <= 0) {
            return false;
        }
        $table = static::tableName();
        $time = time();
        $sql = "update {$table} set usable = usable + {$amount}, recharge = recharge + {$amount}, updated_at = {$time} where user_id = {$this->user_id}";
        if( ! $this->executeQuery($sql)) {
            return false;
        }
        if( ! $this->changer(UserAccountChange::RechargeChange, $amount)) {
            return false;
        }
        $this->usable = $this->usable + $amount;
        $this->recharge = $this->recharge + $amount;
        $this->messager(Message::TypeRecharge, $amount);
        return true;
    }

    /**
     * @name 申请提现，修改用户余额
     * @param $amount int 提现金额
     * @return boolean
     */
    public function applyWithdraw($amount)
    {
        $amount = (int)$amount;
        if($amount <= 0 || $this->usable < $amount) {
            return false;
        }
        $table = static::tableName();
        $time = time();
        $sql = "update {$table} set usable = usable - {$amount}, frozen = frozen + {$amount}, updated_at = {$time} where user_id = {$this->user_id} and usable >= {$amount}";
        if( ! $this->executeQuery($sql)) {
            return false;
        }
        if( ! $this->changer(UserAccountChange::WithdrawApplyChange, - $amount, $amount)) {
            return false;
        }
        $this->usable = $this->usable - $amount;
        $this->frozen = $this->frozen + $amount;
        $this->messager(Message::TypeWithdrawApply, $amount);
        return true;
    }

    /**
     * @name 拒绝提现，修改用户余额
     * @param $amount int 提现金额
     * @return boolean
     */
    public function refuseWithdraw($amount)
    {
        $amount = (int)$amount;
        if($amount <= 0 || $this->frozen < $amount) {
            return false;
        }
        $table = static::tableName();
        $time = time();
        $sql = "update {$table} set usable = usable + {$amount}, frozen = frozen - {$amount}, updated_at = {$time} where user_id = {$this->user_id} and frozen >= {$amount}";
        if( ! $this->executeQuery($sql)) {
            return false;
        }
        if( ! $this->changer(UserAccountChange::WithdrawRefuseChange, $amount, - $amount)) {
            return false;
        }
        $this->usable = $this->usable + $amount;
        $this->frozen = $this->frozen - $amount;
        $this->messager(Message::TypeWithdrawRefuse, $amount);
        return true;
    }

    /**
     * @name 提现到账，修改用户余额
     * @param $amount int 提现金额
     * @return boolean
     */
    public function withdraw($amount)
    {
        // throw new Exception('amount: '.$amount.', frozen:'.$this->frozen);
        $amount = (int)$amount;
        if($amount <= 0 || $this->frozen < $amount) {
            return false;
        }
        $table = static::tableName();
        $time = time();
        $sql = "update {$table} set frozen = frozen - {$amount}, withdraw = withdraw + {$amount}, updated_at = {$time} where user_id = {$this->user_id} and frozen >= {$amount}";
        if( ! $this->executeQuery($sql)) {
            return false;
        }
        if( ! $this->changer(UserAccountChange::WithdrawChange, 0, - $amount)) {
            return false;
        }
        $this->frozen = $this->frozen - $amount;
        $this->withdraw = $this->withdraw + $amount;
        $this->messager(Message::TypeWithdraw, $amount);
        return true;
    }

    /**
     * @name 工资到账，修改用户余额
     * @param $amount int 提现金额
     * @return boolean
     */
    public function earn($amount)
    {
        $amount = (int)$amount;
        if($amount <= 0) {
            return false;
        }
        $table = static::tableName();
        $time = time();
        $sql = "update {$table} set usable = usable + {$amount}, earn = earn + {$amount}, updated_at = {$time} where user_id = {$this->user_id}";
        if( ! $this->executeQuery($sql)) {
            return false;
        }
        if( ! $this->changer(UserAccountChange::EarnChange, $amount, 0)) {
            return false;
        }
        $this->usable = $this->usable + $amount;
        $this->earn = $this->earn + $amount;
        $this->messager(Message::TypeEarn, $amount);
        return true;
    }

    /**
     * @name 支付雇佣费，修改用户余额
     * @param $amount int 雇佣费
     * @return boolean
     */
    public function employment($amount)
    {
        $amount = (int)$amount;
        if($amount <= 0 || $this->usable < $amount) {
            return false;
        }
        $table = static::tableName();
        $time = time();
        $sql = "update {$table} set usable = usable - {$amount}, consume = consume + {$amount}, updated_at = {$time} where user_id = {$this->user_id} and usable >= {$amount}";
        if( ! $this->executeQuery($sql)) {
            return false;
        }
        if( ! $this->changer(UserAccountChange::EmploymentChange, - $amount, 0)) {
            return false;
        }
        $this->usable = $this->usable - $amount;
        $this->consume = $this->consume + $amount;
        $this->messager(Message::TypeEmploymentPay, $amount);
        return true;
    }
    
    /**
     * @name 支付保证金，修改用户余额
     * @param $amount int 雇佣费
     * @return boolean
     */
    public function bond($amount)
    {
        $amount = (int)$amount;
        if($amount <= 0 || $this->usable < $amount) {
            return false;
        }
        $table = static::tableName();
        $time = time();
        $sql = "update {$table} set usable = usable - {$amount}, consume = consume + {$amount}, updated_at = {$time} where user_id = {$this->user_id} and usable >= {$amount}";
        if( ! $this->executeQuery($sql)) {
            return false;
        }
        if( ! $this->changer(UserAccountChange::BondChange, - $amount, 0)) {
            return false;
        }
        $this->usable = $this->usable - $amount;
        $this->consume = $this->consume + $amount;
        $this->messager(Message::TypeBondPay, $amount);
        return true;
    }

    /**
     * @name 添加余额变动日志
     * @return boolean
     */
    public function changer($type, $amount, $frozen = 0)
    {
        $param = [
            'type' => $type,
            'amount' => ($amount < 0) ? - $amount : $amount,
            'pre_change' => $this->usable,
            'after_change' => $this->usable + $amount,
            'after_frozen' => $this->frozen + $frozen,
            'user_id' => $this->user_id,
        ];
        return UserAccountChange::changer($param);
    }
    
    /**
     * @name 添加站内信通知
     * @return boolean
     */
    public function messager($type, $amount)
    {
        $param = [
            'receiver_id' => $this->user_id,
        ];
        return Message::messager($param, $type, [
            'amount' => $amount,
            'time' => time(),
        ]);
    }
}